/*
 * Copyright (C) 2005 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.desktop.plugin.portunis.impl;

import java.awt.EventQueue;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.JMenu;

import nu.zoom.swing.desktop.PlugIn;
import nu.zoom.swing.desktop.Workbench;
import nu.zoom.swing.desktop.WorkbenchFrame;
import nu.zoom.swing.desktop.WorkbenchFrameListener;
import nu.zoom.swing.desktop.WorkbenchListener;
import nu.zoom.swing.desktop.plugin.portunis.ApplicationPreferences;
import nu.zoom.swing.desktop.plugin.portunis.KeyStoreHandler;
import nu.zoom.swing.desktop.plugin.portunis.KeyStoreType;
import nu.zoom.swing.desktop.plugin.portunis.KeyStoreWrapper;
import nu.zoom.swing.desktop.plugin.portunis.Utils;

import org.ops4j.gaderian.Messages;

/**
 * The main plug-in class. This should be registered as a plug-in contribution
 * to the desktop.
 */
public class KeyStorePlugIn implements PlugIn, WorkbenchFrameListener,
        WorkbenchListener {

    private static final String KEYSTORE_MENU_KEY = "nu.zoom.swing.desktop.plugin.portunis.KeyStorePlugIn";
    private final Workbench workbench;
    private final ApplicationPreferences prefs;
    private final KeyStoreHandler keyStoreHandler;
    private Messages messages;
    private JMenu loadedKeyStoreMenu;
    private final HashMap<KeyStoreWrapper, WorkbenchFrame> keyStoreWorkbenchFrames = new HashMap<KeyStoreWrapper, WorkbenchFrame>();

    public KeyStorePlugIn(final Workbench workbench, final ApplicationPreferences prefs,
            final KeyStoreHandler keyStoreHandler) {
        super();
        this.workbench = workbench;
        this.prefs = prefs;
        this.keyStoreHandler = keyStoreHandler;
    }

    public void setMessages(Messages messages) {
        this.messages = messages;
    }

    @Override
    public void initialize() throws Exception {
        workbench.addWorkBenchListener(this);
    }

    synchronized void loadKeystore(File keystoreFile, KeyStoreType type,
            char[] password) throws KeyStoreException,
            NoSuchAlgorithmException, CertificateException,
            FileNotFoundException, IOException {
        if (!keystoreFile.canRead()) {
            workbench.getErrorReporter().reportError(
                    messages.getMessage("keystore.load.unreadable"));
        } else {
            KeyStoreWrapper loadedStore = keyStoreHandler.loadKeyStore(
                    keystoreFile, type, password);
            loadedKeyStoreMenu.removeAll();
            KeyStoreWrapper[] stores = keyStoreHandler.getLoadedKeyStores();
            if ((stores != null) && (stores.length > 0)) {
                loadedKeyStoreMenu.setEnabled(true);
                for (int i = 0; i < stores.length; i++) {
                    loadedKeyStoreMenu.add(new DisplayKeyStoreAction(this,
                            messages, stores[i]));
                }
                displayKeyStore(loadedStore);
            } else {
                loadedKeyStoreMenu.setEnabled(false);
            }
        }
    }

    synchronized void displayKeyStore(KeyStoreWrapper wrapper) {
        WorkbenchFrame frame = keyStoreWorkbenchFrames.get(wrapper);
        if (frame != null) {
            frame.moveToFront();
        } else {
            KeyStoreFrame factory = new KeyStoreFrame(this, keyStoreHandler,
                    prefs, wrapper, messages, workbench);
            try {
                frame = factory.getWorkbenchFrame();
                frame.addFrameListener(this);
                keyStoreWorkbenchFrames.put(wrapper, frame);
            } catch (Exception e) {
                workbench.getErrorReporter().reportError(e);
            }
        }
    }

    @Override
    public synchronized void frameClosed(WorkbenchFrame frame) {
        if (keyStoreWorkbenchFrames.containsValue(frame)) {
            Set<Entry<KeyStoreWrapper, WorkbenchFrame>> set = keyStoreWorkbenchFrames.entrySet();
            KeyStoreWrapper key = null;
            for (Iterator<Entry<KeyStoreWrapper, WorkbenchFrame>> mapEntryIterator = set.iterator(); (mapEntryIterator.hasNext() && (key == null));) {
                Map.Entry<KeyStoreWrapper, WorkbenchFrame> element = mapEntryIterator.next();
                if (frame == element.getValue()) {
                    key = element.getKey();
                }
            }
            if (key != null) {
                keyStoreWorkbenchFrames.remove(key);
            }
        }
    }

    @Override
    public void frameWillDispose(WorkbenchFrame frame) {
    }

    @Override
    public void close() {
    }

    @Override
    public void start() {
        if (!EventQueue.isDispatchThread()) {
            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    startOnEventQueue();
                }
            });
        } else {
            startOnEventQueue();
        }
    }

    /**
     * Start was called. This is the start-stuff that needs to be on the AWT
     * event queue.
     */
    private void startOnEventQueue() {
        JMenu keyStoreMenu = new JMenu(messages.getMessage("keystore.menu"));
        keyStoreMenu.add(new LoadKeyStoreAction(workbench, this, messages));
        loadedKeyStoreMenu = new JMenu(messages.getMessage("keystore.load.loaded"));
        loadedKeyStoreMenu.setEnabled(false);
        loadedKeyStoreMenu.setIcon(Utils.getIconFromMessages(messages,
                "keystore.load.loaded.icon"));
        keyStoreMenu.add(loadedKeyStoreMenu);
        workbench.getMenuBar().addMenu(KEYSTORE_MENU_KEY, keyStoreMenu);
    }

    ApplicationPreferences getPreferences() {
        return prefs;
    }

    Workbench getWorkbench() {
        return workbench;
    }

    @Override
    public void frameDetached(WorkbenchFrame frame) {
    }

    @Override
    public void frameAttached(WorkbenchFrame frame) {
    }

	@Override
	public void visible() {
	}
}
